/*
 * @Author: your name
 * @Date: 2021-07-08 15:11:00
 * @LastEditTime: 2021-12-28 16:19:19
 * @LastEditors: wei_jt@ecidi.com
 * @Description: In User Settings Edit
 * @FilePath: \central-system\src\permission.js
 */
import router from './router'
import { resetRouter } from '@/router'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import store from '@/store'
import { localRoute, behaviorAnalysis, mainApp, socketType } from '@/config'
import { PERMISSIONS, REAL_TIME_PUSH } from '@/store/Getter/getterTypes'
import { SET_PERMISSION, UPDATE_RECEIVED_MESSAGE, UPDATE_PERMISSION_QUEUE } from '@/store/Mutation/mutationTypes'
import { PERMISSION } from '@/store/State/stateTypes'
import { getPermissions } from '@/api/user'
import { getLocalRoutes, getUserRoutes } from '@/utils/route'
import { checkPwdStatus } from '@/utils/password'
import { getDate, getTitle } from '@/utils/monitor'
import { addMonitor } from '@/api/app'
import storage from '@/utils/storage'
import { Notification } from 'fawkes-lib'
import Vue from 'vue'


NProgress.configure({ showSpinner: false }) // NProgress Configuration
function removeLoading () {
  let loading = document.getElementById('main-loading')
  loading && loading.parentNode.removeChild(loading)
}

let first = true


router.beforeEach(async (to, from, next) => {

  // start progress bar
  NProgress.start()

  // 主应用中prefix=''，子应用中prefix='/sub_app_xx'
  let prefix = Vue.prototype.$appBasePath

  switch (true) {
    //重新加载一次基础路由
    //因为第一次加载的时候取不到Vue原型上的值，没法给路由增加异名
    // case (first): {
    //   resetRouter()
    //   first = false
    //   next({ path: to.path, query: to.query, params: to.params, meta: to.meta, replace: true })
    //   return
    // }

    //主应用发现参数带有keepOrgin就去掉
    case (!!(mainApp && to.query?.keepOrigin)): {
      let query = to.query
      delete query.keepOrigin
      next({ path: to.path, query: query, params: to.params, meta: to.meta, replace: true })
      return
    }

    // 子应用模式下重定向
    // 跳转路由时添加/sub_app_xx开头
    case (!!(!to.path.includes(prefix) && !(to.meta?.keepOrigin) && !(to.query?.keepOrigin))): {
      next({ path: prefix + to.path, query: to.query, params: to.params, meta: to.meta, replace: true })
      return
    }

    // 子应用模式下query带有keepOrgin=true,或meta中有keepOrgin:true的
    // 在跳转时不需要添加/sub_app_xx开头
    case (!!((prefix && to.path.includes(prefix) && (to.meta?.keepOrigin || to.query?.keepOrigin)))): {
      next({ path: to.path.replace(prefix, ''), query: to.query, params: to.params, meta: to.meta, replace: true })
      return
    }

    default: {
      break
    }
  }

  let fs = to.matched?.length > 0 && to.meta?.config?.includes('fullScreen')

  if (!fs && !Vue.prototype.$InQianKun) {
    storage.set('redirectUrl', to.fullPath)
  }

  switch (true) {

    //  路由已加载时，跳过加载
    case (store.state.routes.length > 0): {
      // 子应用模式下 路由匹配不到时 直接去掉/sub_app_xx前缀
      // 实际效果是跳出子应用，让主应用来处理这个路由
      if (prefix && to.path.includes(prefix) && (!to.matched || to.matched.length < 1)) {
        next({ path: to.path.replace(prefix, ''), query: { ...to.query, keepOrigin: true }, params: to.params, meta: to.meta, replace: true })
        return
      }
      next()
      break
    }

    //  基础路由部分全屏时，跳过加载
    case (fs): {
      next()
      break
    }

    //  本地路由模式加载
    case (localRoute): {
      let result = getLocalRoutes()

      //这里开ws,去铃铛里订阅
      if (store.getters[REAL_TIME_PUSH]) {
        Vue.prototype.$FksWebsocket({
          name: 'fks-default-websocket',
          connectType: socketType, //'stomp'
          url: Vue.prototype.VUE_APP_SOCKET_API,
          destination: '/topic/message',
          maxReconnect: 2,
          onNewMessage: () => {
            store.commit(UPDATE_RECEIVED_MESSAGE, true)
          }
        })

      }
      next()
      break
    }

    //  线上模式,或基础路由非全屏时，请求路由加载
    default: {
      //读取路由
      let result = await getUserRoutes()

      if (!result) {
        next()
        NProgress.done()
        break
      }

      //这里开ws,去铃铛里订阅
      if (store.getters[REAL_TIME_PUSH]) {
        Vue.prototype.$FksWebsocket({
          name: 'fks-default-websocket',
          connectType: socketType, //'stomp'
          url: Vue.prototype.VUE_APP_SOCKET_API,
          destination: '/topic/message',
          maxReconnect: 2,
          onNewMessage: () => {
            store.commit(UPDATE_RECEIVED_MESSAGE, true)
          }
        })

      }


      //校验密码
      let status = await checkPwdStatus()
      if (status) {
        next({ path: status, replace: true })
        break
      }
      // set the replace: true, so the navigation will not leave a history record
      next({ ...to, replace: true })
    }
  }


})

router.beforeResolve((to, from, next) => {
  if (localRoute || !to.meta || !to.meta.menuId || store.state[PERMISSION][to.meta.menuId]) {
    next()
    return false
  }
  //获取按钮权限
  getPermissions(to.meta.menuId).then(res => {
    res.status && res.data
      && store.commit(SET_PERMISSION, { key: to.meta.menuId, value: res.data })
    next()
  })
})

router.afterEach((to, from) => {
  let prefix = Vue.prototype.$appBasePath

  if (to.path == prefix + '/distribute') {
    router.replace(prefix + '/home')  //多门户首页重复切换报错解决方案
  }

  if (behaviorAnalysis && storage.get('access_token')) {
    if (from?.name && to?.name) {
      addMonitor({
        ev: 'click',//点击事件
        fun: '页面切换',
        mc: to.name,//模块编码
        mn: getTitle(to.name) || to.name,//模块名称
        pa: to.fullPath,//当前页面路由路径
        fpa: from.fullPath,//前置页面路由路径
        fc: from.name,//前置页面模块编码
        fn: getTitle(from.name) || from.name,//前置页面模块名称
        dur: getDate(storage.get('enterTime'), new Date()),//前置页面停留时间
        url: document.location.href,//当前url地址
        sr: `${window.screen.height}x${window.screen.width}`,//屏幕分辨率
        nt: navigator?.connection?.effectiveType,//网络类型
        fl: store.getters.language || '',//当前系统语言
        lan: navigator.language, //浏览器语言
        depthId: storage.get('depthId')//用户访问深度ID
      })
    }
    if (to?.name) {
      storage.set('enterTime', new Date())
    }
  }
  // finish progress bar
  NProgress.done()
  removeLoading()
})

router.onError((error) => {
  Notification.error({
    title: '错误',
    message: '加载的页面发生异常',
  })

  console.error(error)
  NProgress.done()
  removeLoading()
})

export default router

/**
 * @description: 通过code查询用户权限是否已授权
 * @param {String} code 权限编码
 * @param {Object} params 鉴权参数  {Boolean} notFlag 反查标识 | {Array} types 作用门户等级 | {Boolean} entire 全量
 * @return: Boolean
 */
export function nodePermission (codes = [], params = {}) {
  //子应用适配
  let currentStore = Vue.prototype.$InQianKun ? Vue.prototype.$fksMainStore : store
  if (!currentStore) return false

  if (params?.types && currentStore.getters.multiPortal && !params.types.find(type => type == currentStore.state.portal.type)) {
    return true
  }

  let checkCode = (attr) => {
    return currentStore.getters[PERMISSIONS].find(function (item) {
      return attr && attr == item.code
    })
  }

  let findValue

  if (codes instanceof Array) {
    if (params?.entire) {
      findValue = codes.every(code => {
        return code && checkCode(code)
      })
    }
    else {
      findValue = codes.some(code => {
        return code && checkCode(code)
      })
    }
  } else {
    findValue = checkCode(codes)
  }

  checkCode = null

  const rvalue = !!findValue
  return localRoute ? true : (params?.notFlag ? !rvalue : rvalue)
}

export const dataPermission = (codes) => {
  //子应用适配
  let currentStore = Vue.prototype.$InQianKun ? Vue.prototype.$fksMainStore : store
  if (!currentStore) {
    return false
  }
  currentStore.commit(UPDATE_PERMISSION_QUEUE, codes)
}

export const redirectTo = (url) => {
  let to = '/home'
  if (url) {
    to = url
  }
  if (storage.get('redirect') == 1) {
    to = storage.get('redirectUrl') ? storage.get('redirectUrl') : '/home'
    storage.remove('redirect')
  }
  location.replace(location.href.replace(router.currentRoute.path, to))
}